//go:build windows

package windows

import (
	"context"
	"errors"
	"fmt"
	"image"
	"log"
	"time"
)

type Driver struct{}

func (i *Driver) GetScreenSize(display uint) (width, height int, err error) {
	monitors, err := GetMonitors()
	if err != nil {
		return
	}

	return monitors[display].right - monitors[display].left, monitors[display].bottom - monitors[display].top, nil
}

func (i *Driver) Capture(display uint, rgb bool) (img *image.RGBA, err error) {
	sess, err := NewDirectX11Session(display, rgb)
	if err != nil {
		return
	}
	defer sess.Close()

	img, err = sess.Capture()
	if err != nil {
		return nil, err
	}

	return
}

func (i *Driver) Listen(ctx context.Context, display, fps uint, rgb bool, ch chan *image.RGBA) (err error) {
	if ch == nil {
		return fmt.Errorf("channel is nil")
	}

	sess, err := NewDirectX11Session(display, rgb)
	if err != nil {
		return
	}
	defer sess.Close()

	var next bool
	var cache *image.RGBA

	if fps <= 0 {
		fps = 1000
	}

	ticker := time.NewTicker(time.Second / time.Duration(fps))
	defer ticker.Stop()

	var done bool
	for !done {
		select {
		case <-ctx.Done():
			done = true
		case <-ticker.C:
			next = true
		default:
			if !next {
				continue
			}
			next = false
			var img *image.RGBA
			img, err = sess.Capture()
			if errors.Is(err, DXGI_ERROR_WAIT_TIMEOUT) {
				img = cache
				err = nil
			}
			if err != nil {
				return err
			}
			cache = img

			select {
			case ch <- img:
			default:
				log.Println("screen capture channel is full")
			}
		}
	}

	return
}
